import os
import signal
import sys
from typing import Dict, Type

from tornado.ioloop import IOLoop
from tornado.web import Application, RequestHandler
from python_microservice_sdk.eureka_client import eureka_client

from python_microservice_sdk import config as cfg
from python_microservice_sdk.basic_services.self_update import self_update_handler_tuple
from python_microservice_sdk.stub.python_stub import generate_stub_to_file
from python_microservice_sdk.stub.java_stub import generate_java_stub_to_file

# 维护一个python服务列表
python_service_list: Dict[str, Type[RequestHandler]] = {}


def start(config: dict = None, verbose: bool = True):
    # 判断是否有其余参数
    if len(sys.argv) == 3:
        run_scripts(config)
    else:
        # 防重入机制：写入pid文件
        pid_fd = open(os.path.join(os.path.curdir, "pid"), "w")
        pid_fd.write(str(os.getpid()))
        pid_fd.flush()

        # 加载配置
        cfg.load_config(config)
        if verbose:
            print("starting microservice [{0}]".format(
                cfg.PYTHON_SERVICE_CONFIG["app_name"]))

        handlers = list(python_service_list.items())

        # 加入自更新机制
        handlers.append(self_update_handler_tuple)

        app = Application(handlers=handlers)

        if verbose:
            for url in python_service_list:
                print("loaded url handler '%s'" % url)

        app.listen(
            port=cfg.PYTHON_SERVICE_CONFIG["instance_port"],
            address=cfg.PYTHON_SERVICE_CONFIG["instance_host"],
        )

        eureka_client.init(
            **cfg.PYTHON_SERVICE_CONFIG
        )

        loop = IOLoop.current()

        def service_close_handler():
            loop.stop()
            print("微服务已停止")

        signal.signal(signal.SIGINT, lambda sig,
                      frame: loop.add_callback_from_signal(service_close_handler))

        loop.start()


def run_scripts(config: dict = None):
    if sys.argv[1] == "--generate_stub":
        cfg.load_config(config)
        app_name = cfg.PYTHON_SERVICE_CONFIG["app_name"]
        stub_dir = sys.argv[2]
        stub_filepath = os.path.join(
            stub_dir, app_name+".py")
        generate_stub_to_file(stub_filepath, app_name, python_service_list)

    elif sys.argv[1] == "--generate_java_stub":
        cfg.load_config(config)
        app_name = cfg.PYTHON_SERVICE_CONFIG["app_name"]
        stub_dir = sys.argv[2]
        generate_java_stub_to_file(
            stub_dir, app_name, python_service_list)
    else:
        raise NotImplementedError("未知的命令行参数[\"{0}\"]".format(sys.argv[1]))
